import { IPageData } from '../../typings';

function typeOf(value: string): string {
  //原始值:
  //typeof('123') -> 'string';
  //toString.call('123') -> '[object String]'
  //typeof(123) -> 'number';
  //toString.call(123) -> '[object Number]'
  //typeof(null) -> 'object';
  //toString.call(null) -> '[object Null]'
  //typeof(NaN) -> 'number';
  //toString.call(NaN) -> '[object Number]'
  //typeof(undefined) -> 'undefined';
  //toString.call(undefined) -> '[object Undefined]'
  //typeof(true) -> 'boolean';
  //toString.call(true) -> '[object Boolean]'

  //引用值
  //typeof({}) -> 'object';
  //toString.call({}) -> '[object Object]'
  //typeof([]) -> 'object';
  //toString.call([]) -> '[object Array]'
  //typeof(function(){}) -> 'function';
  //toString.call(function(){}) -> '[object Function]'

  //包装类
  //typeof(new Number(1)) -> 'object';
  //toString.call(new Number(1)) -> '[object Number]'
  //typeof(new String('1')) -> 'object';
  //toString.call(new String('123')) -> '[object String]'
  //typeof(new Boolean(true)) -> 'object';
  //toString.call(new Boolean(true)) -> '[object Boolean]'

  //总结: typeof({}|[]|null|包装类) 结果都为 'object'

  //排除null
  if (value === null) {
    return 'null';
  }

  //区分 Object 和 Array
  if (typeof value === 'object') {
    const types = {
      '[object Object]': 'Object',
      '[object Array]': 'Array'
    };

    const ret = Object.prototype.toString.call(value);
    return types[ret];
  } else {
    //返回原始值
    return typeof value;
  }
}

/**
 * 格式化请求路径
 * @param data params对象
 * @param appkey key字段
 * @returns 拼接好符合格式的路径
 */
function formatParams(data: any, appkey: string): string {
  //确保data是一个对象
  if (typeOf(data) !== 'Object') {
    throw new Error('Option "data" must be a type Object');
  }

  /**
   * data: {
   *   type: 'top'
   * }
   */

  //请求示例：http://v.juhe.cn/toutiao/index?type=top&key=APPKEY

  //从?开始拼接
  let paramStr: string = '?';

  for (let key in data) {
    paramStr += `${key}=${data[key]}&`;
  }

  //如果有appkey再次拼接后半段 并排除 & (slice截取区间为第0位到倒数第1位)
  return appkey ? paramStr + 'key=' + appkey : paramStr.slice(0, -1);
}

/**
 * 对拿到的所有列表数据进行处理(根据页码和数量显示条数)
 * @param data 获取到的所有列表数据
 * @param pageNum 页码
 * @param count 每页返回条数
 */
//备注：<T> 为泛型 由于data数据里面的内容是无法认识的,所有需要用泛型,在使用时,谁使用就再定义类型
function getPageData<T>(
  data: Array<T>,
  pageNum: number,
  count: number
): IPageData<T> {
  //给返回的数据信息新增属性hasMore
  const retInfo: IPageData<T> = {
    //告诉前端还有没有更多的数据了
    hasMore: true,
    //当前页的数据
    data: []
  };

  //只有一页时
  if (data.length <= count) {
    //用新定义的data拼接接收到的data成为一个新的数字
    retInfo.data?.concat(data);
    retInfo.hasMore = false;
  } else {
    //不仅有一页时
    //向上取整拿到 页码数量=总数据长度/每页返回条数
    const pageCount: number = Math.ceil(data.length / count);

    //当页码 > 页码数量时说明不可能有数据了
    if (pageNum >= pageCount) {
      retInfo.data = null;
      retInfo.hasMore = false;
    } else {
      //还有更多的页码时对数据进行切分 返回对应页面 对应条数的数据
      //每页数据数量 = 页码 * 条数
      //截取区间(第几位, 第几位)
      retInfo.data = data.splice(pageNum * count, count);
      retInfo.hasMore = true;
    }
  }

  return retInfo;
}

export { formatParams, typeOf, getPageData };
